/**
 * 
 */
package core.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

/**
 * @author Eric
 */
public class UserCF {

	
	/** 
	 * 用户--影视集合
	 * 0  200 201 202
	 * 1  200 300 301
	 * 2  300 302 201
	 * 3  201 205 300 
	 */
	static Multimap<Integer, Integer> userMapMovie = HashMultimap.create();
	
	static Multimap<Integer, Integer> movieMapUser = HashMultimap.create();
	
	/** 相似度矩阵 */
	static double[][] sparseMatrix = new double[4][4];
	
	static {
		userMapMovie.put(0, 200);userMapMovie.put(0, 201);userMapMovie.put(0, 202);
		userMapMovie.put(1, 200);userMapMovie.put(1, 300);
		userMapMovie.put(2, 300);userMapMovie.put(2, 302);
		userMapMovie.put(3, 201);userMapMovie.put(3, 205);userMapMovie.put(3, 300);
		
		for(Entry<Integer,Collection<Integer>> entry : userMapMovie.asMap().entrySet()) {
			for(Integer movieId : entry.getValue()) {
				//建立影视--用户倒排表
				movieMapUser.put(movieId, entry.getKey());
			}
		}
	}
	
	public static void main(String[] args) {
		System.out.println(userMapMovie);
		System.out.println(movieMapUser);

		for(Entry<Integer,Collection<Integer>> entry : movieMapUser.asMap().entrySet()) {
			for(Integer user_u : entry.getValue()) {
				for(Integer user_v : entry.getValue()) {
					if(user_u == user_v) {
						continue;
					}
					sparseMatrix[user_u][user_v] += 1;
				}
			}
		}
		
		for(Entry<Integer,Collection<Integer>> entry : movieMapUser.asMap().entrySet()) {
			for(Integer user_u : entry.getValue()) {
				for(Integer user_v : entry.getValue()) {
					if(user_u == user_v) {
						continue;
					}
					//计算相似度
					sparseMatrix[user_u][user_v]
							= new BigDecimal(
									((sparseMatrix[user_u][user_v])/Math.sqrt((double)(userMapMovie.get(user_u).size() * userMapMovie.get(user_v).size())))
									).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
				}
			}
		}
		
		/**
		 * 用户对物品的感兴趣程度：用户u与候选物品所属用户v 的相似度  * 用户v对该物品的喜爱程度（通常以评分代入）
		 */
		
		for(int i=0; i<4; i++) {
			for(int j=0; j<4; j++) {
				System.out.print(sparseMatrix[i][j] + "    ");
			}
			System.out.println("\n");
		}
		
		int userId = 3;  //TODO
		Set<Integer> candidateItems = pickCandidateItems(sparseMatrix, userId);
		
	}
	
	
	/**
	 * 挑出候选物品列表
	 * --->>初步定10个相似用户  找8个兴趣影视信息
	 * @param array
	 * @param userId
	 * @return
	 */
	private static Set<Integer> pickCandidateItems(double[][] array, Integer userId) {
		//候选物品列表
		Set<Integer> candidateItems = new TreeSet<>();
		
		List<Integer> similarUser = new ArrayList<>();
		
		/** userId:相似权重 */
		Map<Integer, Double> map = new HashMap<>();
		
		for(int i=0; i<array[userId].length; i++) {
			if(array[userId][i] == 0) {
				continue;
			}
			map.put(i, array[userId][i]);
		}

		/** 找出相似度高的list */
		List<Entry<Integer, Double>> sortList = map.entrySet().stream().sorted((n1,n2)->n2.getValue().compareTo(n1.getValue())).collect(Collectors.toList());
		System.out.println(sortList);
		int num = 2;
		for(int i=0; i<num; i++) {
			int id = sortList.get(i).getKey();
			for(Integer movieId : userMapMovie.get(id)) {
				if(!userMapMovie.get(userId).contains(movieId)) {  //剔除原用户感兴趣的物品
					candidateItems.add(movieId);
				}
			}
			similarUser.add(i);
		}
		
		for(int id : candidateItems) {
			
			/** 取交集  候选物品的user 交集  相似度高的user */
			Collection<Integer> retainList = new ArrayList<>();
			retainList.addAll(movieMapUser.get(id));
			retainList.retainAll(similarUser);
			double Pui = 0;
			
			for(Integer i : retainList) {
				double Wuv = sparseMatrix[userId][i];
				double Rvi = 1;  //TODO 评分代入
				Pui += Wuv * Rvi;
			}
			System.out.println(Pui);
		}
		
		return candidateItems;
	}
}
